module klang.编译.语法节点.节点_;
import 全局;
import std.conv: ·to = to;
import klang.编译.类型.枚举值.枚举值_: SK, TK;
import klang.编译.路径.路径_: 路径_;
import klang.编译.类型.类型_: 解析的模块名称_, 类型_, 符号_, 流节点_, 符号表_, 文本范围_, 语法系统标志_, 语法系统_, 三元结果_;
import klang.编译.输出节点.输出节点_: 输出节点_;
import klang.编译.核心.核心_: 词典_, 整数_;
import klang.编译.诊断.诊断_: 诊断_;
alias 令牌种类_ = SK;
class 分离注释信息_ {
    long nodePos;
    long detachedCommentEndPos;
    this() { }
    this(long nodePos, long detachedCommentEndPos) {
        this.nodePos = nodePos;
        this.detachedCommentEndPos = detachedCommentEndPos;
    }
}
class 节点_ : 语法系统_ {
    long 目标种类;
    节点_ 父节点;
    节点数组_!(节点_) jsDoc;
    /* @internal */ 节点_ 原始节点; // The original node if this is an updated node.
    /* @internal */ 符号_ 符号; // Symbol declared by node (initialized by binding)
    /* @internal */ 符号表_ 本地组; // Locals associated with node (initialized by binding)
    /* @internal */ 节点_ 下个容器; // Next container in declaration order (initialized by binding)
    /* @internal */ 流节点_ 流节点; // Associated FlowNode (initialized by binding)
    /* @internal */ 输出节点_ 输出节点; // Associated EmitNode (initialized by transforms)
    /* @internal */ 类型_ 约束类型; // Used to temporarily assign a contextual type during overload resolution
    bool 后面是逗号;
    /*  @internal 增量节点 */
    节点_[] children;
    bool intersectsChange;
    bool hasBeenIncrementallyParsed;
    long 源文件id;
    this() { }
    this(long 开始 = -1, long 结束 = -1) {
        super(语法系统标志_.节点_, 0, 开始, 结束);
        this.目标种类 = 0;
        this.父节点 = ··null!(节点_);
        this.jsDoc = ··null!(节点数组_!(节点_));
        this.原始节点 = ··null!(节点_);
        this.符号 = ··null!(符号_);
        this.本地组 = ··null!(符号表_);
        this.下个容器 = ··null!(节点_);
        this.流节点 = ··null!(流节点_);
        this.输出节点 = ··null!(输出节点_);
        this.约束类型 = ··null!(类型_);
        this.children = ··null!(节点_[]);
        this.intersectsChange = false;
        this.hasBeenIncrementallyParsed = false;
        this.后面是逗号 = false;
        this.源文件id = 0;
    }
}
class 令牌_(T) : 节点_ {
    this() { }
    this(T sk, long 开始 = -1, long 结束 = -1) {
        super(开始, 结束);
        this.种类 = sk;
    }
}
class 注释节点_ : 节点_ {
    dstring 内容;
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(开始, 结束);
        this.种类 = sk;
        this.内容 = ··null!(dstring);
    }
}
class 单行注释_ : 注释节点_ {
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.种类 = SK.单行注释;
        this.内容 = ··null!(dstring);
    }
}
class 多行注释_ : 注释节点_ {
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.种类 = SK.多行注释;
    }
}
class 字面量类节点_ : 注释节点_ {
    dstring 原始文本;
    bool 有万维码转义 = false;
    bool 是未完成的 = false;
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.内容 = ··null!(dstring);
        this.原始文本 = ··null!(dstring);
    }
}
class 数字字面量_ : 字面量类节点_ {
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.种类 = SK.数字字面量;
    }
}
class 文本字面量_ : 字面量类节点_ {
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.种类 = SK.文本字面量;
    }
}
class 标识符_ : 字面量类节点_ {
    this() { }
    this(SK sk, long 开始 = -1, long 结束 = -1) {
        super(sk, 开始, 结束);
        this.种类 = SK.标识符;
    }
}
class 前端节点_ : 节点_ {
    this() { }
    this(TK tk, long tsk, long 开始 = -1, long 结束 = -1) {
        super(开始, 结束);
        this.种类 = SK.目标;
        this.目标 = tk;
        this.目标种类 = tsk;
    }
}
class 模块导入信息_ : 文本范围_ {
    dstring 模块名;
    this() { }
    this(dstring 模块名, long 开始, long 结束) {
        this.模块名 = 模块名;
        this.开始 = 开始;
        this.结束 = 结束;
    }
}
class 源文件类基类_ : 前端节点_ {
    dstring 内容;
    路径_ 文件名;
    /** @internal */
    路径_ 路径;
    /** @internal */
    路径_ resolvedPath;
    /** @internal */
    dstring originalFileName;
    /** @internal */
    dstring 输出文件名;
    long[] 行词典;
    this() { }
    this(TK tk, long tsk, long 开始 = -1, long 结束 = -1) {
        super(tk, tsk, 开始, 结束);
        this.内容 = ··null!(dstring);
        this.文件名 = ··null!(路径_);
        this.路径 = ··null!(路径_);
        this.resolvedPath = ··null!(路径_);
        this.originalFileName = ··null!(dstring);
        this.行词典 = ··null!(long[]);
        this.输出文件名 = ··null!(dstring);
    }
}
class 源文件_ : 源文件类基类_ {
    /** @internal */
    RedirectInfo redirectInfo;
    节点数组_!(节点_) 语句组;
    令牌_!(SK) 文件结尾令牌;
    词典_!(dstring) 标识符映射;
    long 节点数量;
    long 标识符数量;
    long 符号数量;
    词典_!(dstring) 重命名支持;
    词典_!(解析的模块名称_) resolvedModules;
    /* @internal */ 诊断_[] 编译诊断;
    /* @internal */ 诊断_[] 绑定诊断;
    /* @internal */ 诊断_[] 检查诊断;
    /* @internal */ 诊断_[] jsDoc诊断;
    /* @internal */ 诊断_[] 附加诊断;
    模块导入信息_[] 导入组;
    bool 是默认支持库;
    this() { }
    this(TK tk, long tsk, long 开始 = -1, long 结束 = -1) {
        super(tk, tsk, 开始, 结束);
        this.种类 = SK.源文件;
        this.redirectInfo = ··null!(RedirectInfo);
        this.语句组 = ··null!(节点数组_!(节点_));
        this.文件结尾令牌 = ··null!(令牌_!(SK));
        this.标识符映射 = ··null!(词典_!(dstring));
        this.导入组 = ··null!(模块导入信息_[]);
        this.节点数量 = 0;
        this.标识符数量 = 0;
        this.符号数量 = 0;
        this.resolvedModules = ··null!(词典_!(解析的模块名称_));
        this.是默认支持库 = false;
    }
}
class 增量节点_ {
    节点_ 内部节点;
    节点_ parent;
    int length;
    private 节点_[] _children;
    bool intersectsChange;
    bool hasBeenIncrementallyParsed;
    this() { }
    this(节点_ 节点) {
        this.内部节点 = 节点;
    }
}
class 节点数组_(T) {
    T[] 原型;
    this() { this.原型 = ··null!(T[]); }
    immutable this() { this.原型 = ··null!(immutable(T[])); }
    shared this() { this.原型 = ··null!(shared(T[])); }
    this(T[] ·this) {
        this.原型 = ·this;
    }
    const this(const(T[]) ·this) {
        this.原型 = ·this;
    }
    immutable this(immutable(T[]) ·this) {
        this.原型 = ·this;
    }
    shared this(shared(T[]) ·this) {
        this.原型 = ·this;
    }
    long 开始 = -1;
    long 结束 = -1;
    bool 是失踪的 = false;
    bool 有尾随逗号 = false;
    ·U opCast(·U)() {
        if (this is null)
            return null;
        ·U ·ret = new ·U();
        ·ret.原型 = ·to!(typeof(·ret.原型))(原型);
        ·ret.开始 = ·to!(typeof(·ret.开始))(this.开始);
        ·ret.结束 = ·to!(typeof(·ret.结束))(this.结束);
        ·ret.是失踪的 = ·to!(typeof(·ret.是失踪的))(this.是失踪的);
        ·ret.有尾随逗号 = ·to!(typeof(·ret.有尾随逗号))(this.有尾随逗号);
        return ·ret;
    }
    void p·追加(T 元素) {
        this.原型 = .追加!(T)(this.原型, 元素);
    }
    void p·追加(T[] 元素组) {
        this.原型 = .追加!(T)(this.原型, 元素组);
    }
    alias 原型 this;
}
/* @internal */
struct RedirectInfo {
    /** Source file this redirects to. */
    源文件_ redirectTarget;
    /**
     * Source file for the duplicate package. This will not be used by the Program,
     * but we need to keep this around so we can watch for changes in underlying.
     */
    源文件_ unredirected;
    this(源文件_ redirectTarget, 源文件_ unredirected) {
        this.redirectTarget = redirectTarget;
        this.unredirected = unredirected;
    }
}
T 创建节点(T)(SK sk, long 开始 = -1, long 结束 = -1) {
    switch (sk) {
        case SK.未知__:
        case SK.文件结尾:
        case SK.新行:
        case SK.空白:
        case SK.左大括号:
        case SK.右大括号:
        case SK.左括号:
        case SK.右括号:
        case SK.左方括号:
        case SK.右方括号:
        case SK.双引号:
        case SK.单引号:
        case SK.点号:
        case SK.分号:
        case SK.逗号:
        case SK.左尖括号:
        case SK.右尖括号:
        case SK.加号:
        case SK.减号:
        case SK.星号:
        case SK.反斜杠:
        case SK.除号:
        case SK.百分号:
        case SK.且号:
        case SK.或号:
        case SK.异或号:
        case SK.叹号:
        case SK.波折号:
        case SK.美元:
        case SK.问号:
        case SK.冒号:
        case SK.艾特:
        case SK.井号:
        case SK.反引号:
        case SK.等号: {
            令牌_!(SK) n = new 令牌_!(SK)(sk, 开始, 结束);
            return (cast(T)(n));
        }
        case SK.单行注释: {
            单行注释_ n = new 单行注释_(sk, 开始, 结束);
            return (cast(T)(n));
        }
        case SK.多行注释: {
            多行注释_ n = new 多行注释_(sk, 开始, 结束);
            return (cast(T)(n));
        }
        case SK.文本字面量: {
            文本字面量_ n = new 文本字面量_(sk, 开始, 结束);
            return (cast(T)(n));
        }
        case SK.数字字面量: {
            数字字面量_ n = new 数字字面量_(sk, 开始, 结束);
            return (cast(T)(n));
        }
        case SK.标识符: {
            标识符_ n = new 标识符_(sk, 开始, 结束);
            return (cast(T)(n));
        }
        default: break;
    }
    T ret = (cast(T)(new 节点_(开始, 结束)));
    ret.种类 = sk;
    return ret;
}
bool nodeIsSynthesized(文本范围_ 节点) {
    return 节点.开始 < 0 || 节点.结束 < 0;
}
bool positionIsSynthesized(long 开始) {
    return !(开始 >= 0);
}
bool 是失踪列表(T)(节点数组_!(T) arr) {
    return arr.是失踪的;
}
bool 是失踪节点(节点_ 节点) {
    if (节点 is ··null!(节点_)) {
        return true;
    }
    return 节点.开始 == 节点.结束 && 节点.开始 >= 0 && 节点.种类 != SK.文件结尾;
}
bool 是标识符(节点_ n) {
    return n.种类 == SK.标识符;
}
bool 是源文件(节点_ n) {
    return n.种类 == SK.源文件;
}
源文件_ 获取源文件(节点_ n) {
    if (.是源文件(n)) {
        return (cast(源文件_)(n));
    }
    return ··null!(源文件_);
}
标识符_ 获取标识符(节点_ n) {
    if (.是标识符(n)) {
        return (cast(标识符_)(n));
    }
    return ··null!(标识符_);
}
bool 是前端节点(节点_ n) {
    return n.种类 == SK.目标 && n.系统标志 == 语法系统标志_.节点_ && n.目标 != TK.无_;
}
前端节点_ 获取前端节点(节点_ n) {
    if (.是前端节点(n)) {
        return (cast(前端节点_)(n));
    }
    return ··null!(前端节点_);
}
bool 访问节点(bool delegate(节点_) cbNode, 节点_ node = ··null!(节点_)) {
    if (node !is ··null!(节点_)) {
        return cbNode(node);
    }
    return false;
}
bool 访问节点组(bool delegate(节点_) cbNode, bool delegate(节点数组_!(节点_)) cbNodes = ··null!(bool delegate(节点数组_!(节点_))), 节点数组_!(节点_) nodes = ··null!(节点数组_!(节点_))) {
    if ((nodes !is null) && (nodes.原型 !is ··null!(节点_[]))) {
        if (cbNodes !is ··null!(bool delegate(节点数组_!(节点_)))) {
            return cbNodes(nodes);
        }
        foreach (节点_ node; nodes) {
            bool result = cbNode(node);
            if (result) {
                return result;
            }
        }
    }
    return false;
}
// 虚函数
bool 遍历节点(节点_ node, bool delegate(节点_) cbNode, bool delegate(节点数组_!(节点_)) cbNodes = ··null!(bool delegate(节点数组_!(节点_)))) {
    return false;
}
节点_ 查找祖先(节点_ 节点, 三元结果_ delegate(节点_) callback) {
    while(节点 !is ··null!(节点_)) {
        三元结果_ result = callback(节点);
        if (result == 三元结果_.初始_) {
            return ··null!(节点_);
        }
        else if (result == 三元结果_.真_) {
            return 节点;
        }
        节点 = 节点.父节点;
    }
    return ··null!(节点_);
}
